package handle

import (
	"OrderSrv/common/global"
	"OrderSrv/model"
	"OrderSrv/proto"
	"context"
	"encoding/json"
	"fmt"
	"github.com/apache/rocketmq-client-go/v2"
	"github.com/apache/rocketmq-client-go/v2/primitive"
	"github.com/apache/rocketmq-client-go/v2/producer"
	uuid "github.com/satori/go.uuid"
	"go.uber.org/zap"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	"strconv"
)

type OrderServer struct {
}

// rocketmq中消息返回体
type OrderListener struct {
	Code        int32
	Msg         string
	ID          int32
	OrderAmount float32
	Ctx         context.Context
}

// 本地事务 -- 处理业务逻辑
func (dl *OrderListener) ExecuteLocalTransaction(msg *primitive.Message) primitive.LocalTransactionState {
	var orderInfo model.OrderInfo
	_ = json.Unmarshal(msg.Body, &orderInfo)

	//生成订单表
	tx := global.DB.Begin()
	result := tx.Save(&orderInfo)
	//扣减库存

	//延时消息
	p, err := rocketmq.NewProducer(producer.WithNameServer([]string{"127.0.0.1:9876"}), producer.WithGroupName("mxshop"))
	if err != nil {
		panic("生成producer失败")
	}

	if err = p.Start(); err != nil {
		panic("启动producer失败")
	}

	msg = primitive.NewMessage("order_timeout", msg.Body)
	msg.WithDelayTimeLevel(3)
	//同步
	_, err = p.SendSync(context.Background(), msg)
	if err != nil {
		zap.S().Errorf("发送延时消息失败: %v\n", err)
		tx.Rollback()
		dl.Code = 400
		dl.Msg = "发送延时消息失败"
		return primitive.CommitMessageState
	}
	//提交事务
	tx.Commit()
	if result.RowsAffected == 0 {
		tx.Rollback()
		dl.Code = 400
		dl.Msg = "创建订单失败"
		return primitive.RollbackMessageState
	}
	dl.Code = 200
	return primitive.CommitMessageState
}

func (dl *OrderListener) CheckLocalTransaction(msg *primitive.MessageExt) primitive.LocalTransactionState {
	return primitive.RollbackMessageState
}

func (*OrderServer) CreateOrder(ctx context.Context, req *proto.OrderRequest) (*proto.OrderInfoResponse, error) {
	orderListener := OrderListener{Ctx: ctx}
	p, err := rocketmq.NewTransactionProducer(
		&orderListener,
		producer.WithNameServer([]string{"127.0.0.1:9876"}),
	)
	if err != nil {
		zap.S().Errorf("生成producer失败: %s", err.Error())
		return nil, err
	}

	if err = p.Start(); err != nil {
		zap.S().Errorf("启动producer失败: %s", err.Error())
		return nil, err
	}
	orderSnc := uuid.NewV4().String()
	payType := strconv.Itoa(int(req.PayType))
	//即将要入库的结构体
	order := model.OrderInfo{
		OrderSn:    orderSnc,
		User:       req.UserId,
		PayType:    payType,
		OrderMount: req.OrderMount,
	}

	jsonString, _ := json.Marshal(order)
	_, err = p.SendMessageInTransaction(context.Background(),
		primitive.NewMessage("order_put", jsonString))
	if err != nil {
		fmt.Printf("发送失败: %s\n", err)
		return nil, status.Error(codes.Internal, "发送消息失败")
	}
	return &proto.OrderInfoResponse{Id: 112, OrderSn: order.OrderSn}, nil
}

//消费消息
